package com.zcxy.mybatis.service;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zcxy.constant.CommonConstant;
import com.zcxy.core.bean.PageQuery;
import com.zcxy.core.bean.Response;
import com.zcxy.exception.BusinessException;
import com.zcxy.mybatis.bean.BaseEntity;
import com.zcxy.mybatis.bean.SysUser;
import com.zcxy.mybatis.mapper.MyBaseMapper;
import com.zcxy.util.JwtUtil;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @author zcc
 * @version 1.0.0
 * @ClassName baseService.java
 * @Description TODO
 * @createTime 2019年12月04日 11:39:00
 */
public class BaseServiceImpl<M extends MyBaseMapper<T>, T> extends ServiceImpl<M, T> {

    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }
        if ((obj instanceof List)) {
            return ((List) obj).size() == 0;
        }
        if ((obj instanceof String)) {
            return ((String) obj).trim().equals("");//判断Stirng类型的对象是否为空，一个是和null对比，一个是点equal("")
        }
        return false;
    }

    /**
     * 分页查询简化
     *
     * tPageQuery
     * @return
     */
    public Response<IPage<T>> pageQuery(PageQuery<T> tPageQuery, QueryWrapper<T> queryWrapper) {
        Response<IPage<T>> Response = new Response<IPage<T>>();
        Page<T> page = new Page<T>(tPageQuery.getPageNo(), tPageQuery.getPageSize());
        Response.setSuccess(true);
        IPage<T> pageList = page(page, queryWrapper);
        Response.setResult(pageList);
        return Response;
    }

    public List<T> listByEntity(T t) {
        QueryWrapper queryWrapper = new QueryWrapper(t);
        return baseMapper.selectList(queryWrapper);
    }

    public T selectOneByEntity(T t) {
        QueryWrapper queryWrapper = new QueryWrapper(t);
        List<T> ts = baseMapper.selectList(queryWrapper);
        BaseEntity baseEntity = new BaseEntity();
        if (ts.size() > 0) {
            return ts.get(0);
        }
        return null;
    }


    /**
     * validFN  需要判重的字段--驼峰
     * validFV  需要判重的值
     * existFN  排除的字段--驼峰
     * -existFv 排除字段值
     * errInfo  提示
     */
    public void validFiledExistUpdate(String validFN, Object validFV, String existFN, Object existFV, String errInfo) {
        T t = createT();
        // 调用set方法
        try {
            Field fieldValid = t.getClass().getDeclaredField(validFN);
            Assert.notNull(fieldValid, "需要校验重复的字段不存在，请检查传入参数");
            Field fieldVExist = ReflectUtil.getField(t.getClass(), existFN);
            Assert.notNull(fieldVExist, "需要排除的属性的字段不存在，请检查传入参数");
            fieldValid.setAccessible(true);
            fieldValid.set(t, validFV);
            fieldValid.setAccessible(false);
            QueryWrapper queryWrapper = new QueryWrapper(t);
            queryWrapper.notIn(existFN.replaceAll("[A-Z]", "_$0").toLowerCase(), existFV);
            List<T> tList = baseMapper.selectList(queryWrapper);
            if (tList.size() > 0) {
                throw new BusinessException(errInfo);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            throw new BusinessException(validFN + "属性不存在");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new BusinessException(e.getMessage());
        }

    }

    /**
     * validFN 校验重复的属性
     * validFV
     * errInfo
     */
    public void validFiledExistInsert(String validFN, Object validFV, String errInfo) {
        T t = createT();
        try {
            Field fieldValid = t.getClass().getDeclaredField(validFN);
            Assert.notNull(fieldValid, "需要校验重复的字段不存在，请检查传入参数");
            fieldValid.setAccessible(true);
            fieldValid.set(t, validFV);
            fieldValid.setAccessible(false);
            QueryWrapper queryWrapper = new QueryWrapper(t);
            int count = baseMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException(errInfo);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    /**
     * 多属性(组合属性)校验字段重复
     *
     * valiteConditions 属性名称及值组合数组对象
     * errInfo          错误提示
     */
    public void validFiledExistInsert(ValiteCondition valiteConditions, String errInfo) {
        T t = createT();
        try {
            for (int i = 0; i < valiteConditions.getFiledNames().size(); i++) {
                String filedName = valiteConditions.getFiledNames().get(i);
                Object filedValue = valiteConditions.getFildeValues().get(i);
                Field fieldValid = t.getClass().getDeclaredField(filedName);
                if (isEmpty(filedValue)) {
                    continue;
                }
                Assert.notNull(fieldValid, "需要校验重复的字段不存在，请检查传入参数");
                fieldValid.setAccessible(true);
                fieldValid.set(t, filedValue);
                fieldValid.setAccessible(false);
            }
            QueryWrapper queryWrapper = new QueryWrapper(t);
            int count = baseMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException(errInfo);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 多属性(组合属性)校验修改重复
     *
     * valiteConditions         属性名称及值组合数组对象
     * existFN：需要排除的当前对象的主键属性名称
     * existFV：需要排除的当前对象的主键属性值
     * errInfo：错误提示
     */

    public void validFiledExistUpdate(ValiteCondition valiteConditions, String existFN, Object existFV, String errInfo) {
        T t = createT();
        // 调用set方法
        try {
            for (int i = 0; i < valiteConditions.getFiledNames().size(); i++) {
                String filedName = valiteConditions.getFiledNames().get(i);
                Object filedValue = valiteConditions.getFildeValues().get(i);
                if (isEmpty(filedValue)) {
                    continue;
                }
                Field fieldValid = t.getClass().getDeclaredField(filedName);
                Assert.notNull(fieldValid, "需要校验重复的字段不存在，请检查传入参数");
                fieldValid.setAccessible(true);
                fieldValid.set(t, filedValue);
                fieldValid.setAccessible(false);
            }
            QueryWrapper queryWrapper = new QueryWrapper(t);
            queryWrapper.notIn(existFN.replaceAll("[A-Z]", "_$0").toLowerCase(), existFV);
            int count = baseMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException(errInfo);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            throw new BusinessException("属性不存在");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new BusinessException(e.getMessage());
        }
    }

    public T createT() {
        T t = null;
        try {
            ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
            Class<T> tClass = (Class<T>) parameterizedType.getActualTypeArguments()[1];
            t = tClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return t;
    }

    public void insertDefualtValue(T i) {
        try {
            Field[] fields = ReflectUtil.getFields(i.getClass());
            for (Field field : fields) {
                if (!("createBy".equals(field.getName()) || "createTime".equals(field.getName()) || "updateTime".equals(field.getName()) || "updateBy".equals(field.getName()) || "delFlag".equals(field.getName()))) {
                    continue;
                }
                log.debug("------field.name------" + field.getName());
                SysUser sysUser = JwtUtil.getLoginUser();
                // 获取当前的用户
                if ("createBy".equals(field.getName())) {
                    field.setAccessible(true);
                    Object local_createBy = field.get(i);
                    field.setAccessible(false);
                    if (local_createBy == null || local_createBy.equals("")) {
                        String createBy = "admin";
                        if (sysUser != null) {
                            // 登录账号
                            createBy = sysUser.getLoginName();
                        }
                        if (StringUtils.isNotEmpty(createBy)) {
                            field.setAccessible(true);
                            field.set(i, createBy);
                            field.setAccessible(false);
                        }
                    }
                }
                // 注入创建时间
                else if ("createTime".equals(field.getName())) {
                    field.setAccessible(true);
                    Object local_createDate = field.get(i);
                    field.setAccessible(false);
                    if (local_createDate == null || local_createDate.equals("")) {
                        field.setAccessible(true);
                        field.set(i, new Date());
                        field.setAccessible(false);
                    }
                } else if ("updateBy".equals(field.getName())) {
                    field.setAccessible(true);
                    try {
                        Object local_updateBy = field.get(i);
                        field.setAccessible(false);

                        String updateBy = "admin";
                        if (sysUser != null) {
                            // 登录账号
                            updateBy = sysUser.getLoginName();
                        }
                        if (StringUtils.isNotEmpty(updateBy)) {
                            field.setAccessible(true);
                            field.set(i, updateBy);
                            field.setAccessible(false);
                        }

                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                } else if ("updateTime".equals(field.getName())) {
                    field.setAccessible(true);
                    try {
                        field.set(i, new Date());
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    field.setAccessible(false);
                } else if ("delFlag".equals(field.getName())) {
                    field.setAccessible(true);
                    Object local_delFlag = field.get(i);
                    field.setAccessible(false);
                    if (local_delFlag == null || local_delFlag.equals("")) {
                        field.setAccessible(true);
                        field.set(i, CommonConstant.DEL_FLAG_1);
                        field.setAccessible(false);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new BusinessException(e.getMessage());
        }
    }

    @Override
    public boolean saveBatch(Collection<T> entityList) {
        entityList.stream().forEach(i -> {
            insertDefualtValue(i);
        });

        return ((MyBaseMapper)super.getBaseMapper()).insertBatchSomeColumn(entityList)>0;
    }

    @Override
    public boolean saveOrUpdateBatch(Collection<T> entityList) {
        entityList.stream().forEach(i -> {
            insertDefualtValue(i);
        });
        return super.saveOrUpdateBatch(entityList);
    }

    @Override
    public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
        entityList.stream().forEach(i -> {
            insertDefualtValue(i);
        });
        return super.saveOrUpdateBatch(entityList, batchSize);
    }


    @Override
    public boolean save(T entity) {
        insertDefualtValue(entity);
        return super.save(entity);
    }

    @Override
    public boolean saveOrUpdate(T entity) {
        insertDefualtValue(entity);
        return super.saveOrUpdate(entity);
    }

}
